<?php
/**
 * CGroupDataProvider implements a data provider based on ActiveRecord.
 *
 * CGroupDataProvider provides data in terms of ActiveRecord objects which are
 * of class {@link modelClass}. It uses the AR {@link CActiveRecord::findAll} method
 * to retrieve the data from database. The {@link criteria} property can be used to
 * specify various query options, such as conditions, sorting, pagination, etc.
 *
 * CGroupDataProvider may be used in the following way:
 * <pre>
 * $dataProvider=new CGroupDataProvider('Post', array(
 *     'criteria'=>array(
 *         'condition'=>'status=1',
 *         'order'=>'create_time DESC',
 *         'with'=>array('author'),
 *     ),
 *     'pagination'=>array(
 *         'pageSize'=>20,
 *     ),
 * ));
 * // $dataProvider->getData() will return a list of Post objects
 * </pre>
 *
 * @author Andrey Borodulin <borodulin@gmail.com>
 * @version
 * @package
 * @since
 */
class CGroupDataProvider extends CActiveDataProvider
{

	private $_group;

	/**
	 * Returns the grouping object.
	 * @return CGroup the grouping object. If this is false, it means the grouping is disabled.
	 */
	public function getGroup()
	{
		if($this->_group===null)
		{
			$this->_group=new CSort;
			if(($id=$this->getId())!='')
				$this->_group->groupVar=$id.'_group';
		}
		return $this->_group;
	}

	
	/**
	 * Sets the grouping for this data provider.
	 * @param mixed $value the grouping to be used by this data provider. This could be a {@link CGroup} object
	 * or an array used to configure the grouping object. If this is false, it means the grouping should be disabled.
	 */
	public function setGroup($value)
	{
		if(is_array($value))
		{
			$group=$this->getGroup();
			foreach($value as $k=>$v)
				$group->$k=$v;
		}
		else
			$this->_group=$value;
	}	
	
	/**
	 * Fetches the data from the persistent data storage.
	 * @return array list of data items
	 */
	protected function fetchData()
	{
		$criteria=clone $this->getCriteria();
		$baseCriteria=$this->model->getDbCriteria(false);

		if(($pagination=$this->getPagination())!==false)
		{
			if($baseCriteria!==null)
				$this->model->setDbCriteria(clone $baseCriteria);
			$pagination->setItemCount($this->getTotalItemCount());
			$pagination->applyLimit($criteria);
		}

		
		if(($group=$this->getGroup())!==false)
		{
			if($baseCriteria!==null)
			{
				$c=clone $baseCriteria;
				$c->mergeWith($criteria);
				$this->model->setDbCriteria($c);
			}
			else
				$this->model->setDbCriteria($criteria);
				
			$order=$group->getOrderBy();
			if(!empty($order))
			{
				if(!empty($criteria->order))
					$criteria->order=$order.', '.$criteria->order;
				else
					$criteria->order=$order;
			}	
		}		
		
		if(($sort=$this->getSort())!==false)
		{
			if($baseCriteria!==null)
			{
				$c=clone $baseCriteria;
				$c->mergeWith($criteria);
				$this->model->setDbCriteria($c);
			}
			else
				$this->model->setDbCriteria($criteria);
			$sort->applyOrder($criteria);
		}
		
		$this->model->setDbCriteria($baseCriteria);
		return $this->model->findAll($criteria);
	}
}
